<template>
  <div class="h-uploader h-uploader-image-container" style="width: 120px;height: 120px;min-height: 20px;" ref="drag">
    <input ref="fileInput" type="file" :accept="accept?accept:''"
           style="display: none;" @change="addFile">
    <div class="h-uploader-item" v-if="item.path">
      <img v-if="item.type=='img'" :src="resolvePath(item.path)" style="width: 100%;height: 100%"/>
      <div style="text-align: center;padding:10px;width: 100%;overflow: hidden;text-overflow: ellipsis;" v-else>
<!--        {{ item.name }}-->
        <Icon type="icon-file" style="font-size: 4rem;color:#909399;"/>
      </div>
      <Progress v-if="item.percent<100" :percent="item.percent" :strokeWidth="5" color="#ff5500"
                style="position: absolute;bottom: 2px;width: 100%;">
      </Progress>
      <div class="h-uploader-actions">
            <span class="h-uploader-action" v-if="item.removing">
               <i class=" h-icon-spinner"></i>
            </span>
        <template v-else>
              <span class="h-uploader-action" v-if="item.type=='img'" @click="preview(item)">
                <i class="h-icon-search"></i>
              </span>
          <span class="h-uploader-action" v-else @click="download">
                <i class="h-icon-inbox"></i>
              </span>
          <span class="h-uploader-action" @click="deleteFile" v-if="!props.readonly">
                   <i class="h-space" style="width: 10px;"></i>
                  <i class="h-icon-trash"></i>
               </span>
        </template>
      </div>
    </div><!---->
    <div v-else-if="!props.readonly" class="h-uploader-item add" @click="addFileClick">
      <i class="h-icon-plus"></i>
    </div>
    <Loading :loading="item.uploading" style="width: 100%;height: 100%;background: rgba(0,0,0,.3);border-radius: 6px;"></Loading>
  </div>
</template>

<script setup>
import {ref, reactive, onMounted, onBeforeUnmount, watch} from 'vue'
import axios from 'axios'
import {ajax} from 'framework'
import {imagePreview, message} from 'HeyUI';

const CancelToken = axios.CancelToken;

const drag = ref(null), fileInput = ref(null)
const active = ref(false)
const files = ref([])
const file = ref(null)

const multiple = ref(false)

const emit = defineEmits(['update:modelValue', 'delete','change'])
const props = defineProps({
  modelValue: {
    type: String,
    default: ''
  },
  readonly: {
    type: Boolean,
    default: false
  },
  //支持的后缀类型*.jpg,*.xx
  accept: {
    type: String
  },
  limit:1,
  maxSize:{
    type:String,
    default:"10M"
  },
  uploadPath: {
    type: String,
    default: 'file/upload'
  },
  deletePath: {
    type: String,
    default: 'file/delete'
  }
})
const accept = ref(props.accept)

const item = reactive({
  path: props.modelValue,
  name: null,
  removing: false,
  type: "file",
  percent: 100,
  uploading:false
})
//B,K,M,G
const sizeMap={
  B:'',
  K:'*1024',
  M:'*1024*1024',
  G:'*1024*1024*1024',
  T:'*1024*1024*1024*1024'
}
const maxFileSize=eval(props.maxSize.toUpperCase().replace(/[BKMG]/,s=>sizeMap[s]));

onMounted(() => {
  drag.value.addEventListener('drop', handleDrop)
  drag.value.addEventListener('dragleave', (e) => {
    active.value = false
    e.preventDefault()
  })
  drag.value.addEventListener('dragenter', (e) => {
    active.value = true
    e.preventDefault()
  })
  drag.value.addEventListener('dragover', (e) => {
    active.value = true
    e.preventDefault()
  })
  setItemsFromValues()
})
watch(() => props.modelValue, setItemsFromValues)

accept.value = props.accept

watch(() => props.accept, (v) => accept.value = v)

onBeforeUnmount(() => {
  drag.value.removeEventListener('drop', handleDrop)
})

function setItemsFromValues() {
    item.path=props.modelValue
    if(item.path&&/(jpg)|(png)|(jpeg)|(gif)|(svg)|(webp)$/.test(item.path.toLowerCase())){
      item.type='img'
    }else{
      item.type='file'
    }
}

function updateValue() {
  emit('update:modelValue', item.path)
}


async function uploadFile(file) {
  if (props.readonly) {
    return;
  }
  if(file.size>maxFileSize){
    message("文件超过"+props.maxSize)
    return
  }
  let cancelToken;
  Object.assign(item,{
    percent: 0,
    name: file.name,
    path: '',
    removing: false,
    cancelUpload() {
      cancelToken.cancel()
    }
  })

  if (/image\/.*/.test(file.type)) {
    let fileReader = new FileReader();
    fileReader.onloadend = function () {
      if (fileReader.readyState == fileReader.DONE) {
        item.type = "img"
        item.path = fileReader.result
        //document.getElementById('img').setAttribute('src', fileReader.result);
      }
    };
    fileReader.readAsDataURL(file);
  } else {
    item.type = "file"
  }
  // const formData = new FormData()
  // formData.append('file', file)
  try{
    item.uploading=true
    // let ret = await axios({
    //   url: props.uploadPath,
    //   method: 'POST',
    //   data: formData,
    //   cancelToken: new CancelToken(function executor(c) {
    //     cancelToken = c;
    //   }),
    //   onUploadProgress(progressEvent) {
    //     item.percent = parseInt(progressEvent.loaded / progressEvent.total * 100)
    //     console.log(progressEvent.loaded, progressEvent.total,item.percent)
    //   }
    // })
    let ret = await ajax.uploadDirect(file)
    item.path = ret.data
    item.percent = 100
    item.uploading=false
    updateValue()
  }catch (e){
    console.error(e)
    item.percent = 100
    item.uploading=false
    removeFileItem(item)
  }

}

const handleDrop = async (e) => {
  e.preventDefault()
  if (props.readonly) {
    return;
  }
  active.value = false
  for (let file of e.dataTransfer.files) {
    // if (file.type == '') {
    //   message({type: 'warn', text: '文件"' + file.name + '"因类型不符已被排除'})
    //   continue
    // }
    if (filterType(file.name)) {
      message({type: 'warn', text: '文件"' + file.name + '"因类型不符已被排除'})
      continue
    }
    await uploadFile(file)
    break;
  }
}

function filterType(name) {
  if (!props.accept) {
    return false
  }
  let type = name.substring(name.lastIndexOf(".")).toLowerCase();
  if (props.accept.indexOf(type) == -1) {
    return true
  }
  return false
}

function addFileClick() {
  fileInput.value.click()
}

async function addFile(e) {
  for (let file of e.target.files) {
    // if (file.type == '') {
    //   continue
    // }
    if (filterType(file.name)) {
      continue
    }
    await uploadFile(file)
  }
  e.target.value = null
}

function removeFileItem(item) {
  item.path=''
  updateValue()
}

function deleteFile() {
  emit("delete", item)
  if (item.percent > -1 && item.percent < 100) {
    item.cancelUpload()
    removeFileItem(item)
  } else {
    if (/^https?:\/\//.test(item.path)) {
      removeFileItem(item)
    } else {
      const formData = new FormData()
      formData.append('path', item.path)
      item.removing = true
      axios({
        url: props.deletePath,
        method: 'POST',
        data: formData
      }).then(r => {
        removeFileItem(item)
      }).finally(r => {
        item.removing = false
      })
    }
  }

}

function download() {
  //ajax下载
  ajax.download(resolvePath(item.path))
}
//单文件预览
function preview(item) {
  // let imgs = [];
  // for (let it of files.value) {
  //   if (it.type == 'img') {
  //     imgs.push(it.path)
  //   }
  // }
  // let idx = 0
  // for (let i = 0; i < imgs.length; i++) {
  //   let img = imgs[i]
  //   if (img == item.path) {
  //     idx = i
  //     break
  //   }
  // }
  imagePreview(resolvePath(item.path))
}
function resolvePath(path){
  //console.log(window._configs)
  if(path.startsWith('data:')){
    return path;
  }
  if(window._configs['PlatformConfig.FileSec']=='true'){
    if(path.indexOf('?')>-1){
      return path+"&_token="+sessionStorage._token
    }else{
      return path+"?_token="+sessionStorage._token
    }
  }
  return path
}
</script>

<style lang="less" scoped>
.file-icon {
  font-size: 25px;
  color: #d3d3d3;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.h-uploader-item {
  width: 120px;
  height: 120px;
  display: inline-flex;
  border-radius: 6px;
  box-sizing: border-box;
  overflow: hidden;
  border: 1px solid #dcdfe6;
  margin: 0 8px 8px 0;
  position: relative;
  justify-content: center;
  align-items: center;
  float: left;

  &.add {
    border: 1px dashed #cdd0d6;
    float: left;
    font-size: 28px;
    color: #909399;
  }

  &.add:hover {
    border-color: #409eff;
    color: #409eff;
  }

  .h-uploader-actions {
    position: absolute;
    width: 100%;
    height: 100%;
    left: 0;
    top: 0;
    cursor: default;
    display: inline-flex;
    justify-content: center;
    align-items: center;
    color: #fff;
    opacity: 0;
    font-size: 20px;
    background-color: rgba(0, 0, 0, .3);
    transition: opacity .3s;

    .h-uploader-action {
      cursor: pointer;
    }
  }

  .h-uploader-actions:hover {
    opacity: 1;
    cursor: move;
  }
}

.h-uploader-image-container {
  width: 100%;
}
</style>

<style>
/*设置列表的样式*/
.list-item {
  display: inline-block;
  margin-right: 10px;
}

/*设置列表transition-group的name为list的入场以及离场动画效果*/
.list-enter-active, .list-leave-active {
  transition: all .6s;
}

.list-enter, .list-leave-to
  /* .list-leave-active for below version 2.1.8 */
{
  opacity: 0;
  transform: translateY(30px);
}

/* 下面的 .v-move 和 .v-leave-active 配合使用，能够实现列表后续的元素，渐渐地移动过来的效果 */
.list-move {
  transition: all 0.6s ease;
}

.list-leave-active {
  position: absolute;
}
</style>
